<template>
  <Dialog :title="dialogTitle" v-model="dialogVisible" width="635" :scroll="true">
    <el-row :gutter="10" class="!w-full">
      <el-col :xs="6" :sm="6" :md="6" :lg="6" :xl="4">
        <div class="flex justify-center">
          <el-image :fit="'fill'" :src="state.selectedSku.picUrl || spuItem.picUrl" />
        </div>
      </el-col>
      <el-col :xs="18" :sm="18" :md="18" :lg="18" :xl="20">
        <div class="!h-full flex flex-col justify-between">
          <div>
            <el-text line-clamp="1" class="custom-text-16 c-[#11192d]! .dark:c-[#fff]!">
              <SpuTag
                :type="DICT_TYPE.PRODUCT_SPU_TYPE"
                :value="spuItem.spuType"
                v-if="spuItem.spuType != 2 && spuItem.spuType != 4"
              />
              <SpuTag
                v-if="spuItem.spuType == 2"
                :type="DICT_TYPE.PRODUCT_SPU_TYPE2"
                :value="state.selectedSku!.skuType"
              />
              <SpuTag
                v-if="spuItem.spuType == 4"
                :type="DICT_TYPE.PRODUCT_SPU_TYPE4"
                :value="state.selectedSku!.skuType"
              />

              {{ spuItem.brandId }} {{ spuItem.spuName }}
            </el-text>
          </div>

          <div class="custom-text-14 flex items-center" v-if="state.selectedSku.skuId">
            ID: {{ state.selectedSku.skuId }}<el-divider direction="vertical" />
            <el-tag
              class="mr-5px !h-full p-2px!"
              v-for="property in state.selectedSku.properties"
              :key="property.propertyId"
            >
              {{ property.valueName }}
            </el-tag>

            <el-tag v-if="spuItem.spuType == 2">
              {{ filterCardAttributes(state.selectedSku, true, true) }}
            </el-tag>
          </div>

          <div class="flex items-baseline">
            <div class="custom-text-20 goods-price flex items-baseline">
              <span class="custom-text-12"> ￥ </span>
              <span v-if="state.selectedSku.price">
                {{ fenToYuan(state.selectedSku.price) }}
              </span>
              <span v-else>
                {{
                  isArray(spuItem.price) ? fenToYuan(spuItem.price[0]) : fenToYuan(spuItem.price)
                }}
              </span>
            </div>
            <div class="custom-text-12 decoration-line-through m-l-5px"
              >￥{{ fenToYuan(state.selectedSku.marketPrice || spuItem.marketPrice) }}
            </div>
          </div>
        </div>
      </el-col>
    </el-row>

    <div class="mt-10px mb-10px">
      <div v-for="property in propertyList" :key="property.id">
        <div class="flex flex-col mb-10px">
          <div class="mb-10px">
            {{ property.name }}
          </div>
          <div class="flex flex-wrap">
            <el-button
              v-for="value in property.values"
              :key="value.id"
              :type="state.currentPropertyArray[property.id] === value.id ? 'primary' : ''"
              :disabled="value.disabled === true"
              @click="onSelectSku(property.id, value.id)"
            >
              {{ value.name }}</el-button
            >
          </div>
        </div>
      </div>
    </div>

    <template #footer>
      <el-button @click="addCart" type="primary" :disabled="formLoading">加入购物车</el-button>
      <!-- <el-button @click="onBuy">立即购买</el-button> -->
    </template>
  </Dialog>
</template>
<script setup lang="ts">
import * as ProductSpuApi from '@/api/shop/product/spu'
import { fenToYuan } from '@/utils'
import { getPropertyList } from '../../hooks/useGoods'
import { DICT_TYPE } from '@/utils/dict'
import { isArray } from '@/utils/is'
import { useProductUtils } from '@/views/mall/product/hooks/useProduct'
const { filterCardAttributes } = useProductUtils()
const state = reactive({
  selectedSku: {} as ProductSpuApi.Sku, // 选中的 SKU
  currentPropertyArray: [] as EmptyArrayType // 当前选中的属性，实际是个 Map。key 是 property 编号，value 是 value 编号
})
const message = useMessage() // 消息弹窗

const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中：1）修改时的数据加载；2）提交的按钮禁用
const spuItem = ref() //spu详情
const propertyList = ref<EmptyArrayType>([])
/** 打开弹窗 */
const open = async (spuId?: number) => {
  dialogTitle.value = '商品规格'
  resetState()
  // 修改时，设置数据
  if (spuId) {
    formLoading.value = true
    try {
      spuItem.value = await ProductSpuApi.getSpu(spuId)
      propertyList.value = getPropertyList(spuItem.value.skus)
      console.log(propertyList.value)
      dialogVisible.value = true
      changeDisabled(false)
      if (propertyList.value.length == 1) {
        // 如果只有一个sku默认选择
        onSelectSku(propertyList.value[0].id, propertyList.value[0].values[0].id)
      }
    } finally {
      formLoading.value = false
    }
  }
}
defineExpose({ open }) // 提供 open 方法，用于打开弹窗

// SKU 列表
const skuList = computed(() => {
  let skuPrices = spuItem.value.skus
  for (let price of skuPrices) {
    price.value_id_array = price.properties.map((item) => item.valueId)
  }
  return skuPrices
})
// 改变禁用状态：计算每个 property 属性值的按钮，是否禁用
const changeDisabled = (isChecked = false, propertyId = 0, valueId = 0) => {
  let newSkus = [] as EmptyArrayType // 所有可以选择的 sku 数组
  if (isChecked) {
    // 情况一：选中 property
    // 获得当前点击选中 property 的、所有可用 SKU
    for (let price of skuList.value) {
      // if (price.stock <= 0) {
      //   continue
      // }
      if (price.value_id_array.indexOf(valueId) >= 0) {
        newSkus.push(price)
      }
    }
  } else {
    // 情况二：取消选中 property
    // 当前所选 property 下，所有可以选择的 SKU
    newSkus = getCanUseSkuList()
  }

  // 所有存在并且有库存未选择的 SKU 的 value 属性值 id
  let noChooseValueIds = [] as EmptyArrayType
  for (let price of newSkus) {
    noChooseValueIds = noChooseValueIds.concat(price.value_id_array)
  }
  noChooseValueIds = Array.from(new Set(noChooseValueIds)) // 去重

  if (isChecked) {
    // 去除当前选中的 value 属性值 id
    let index = noChooseValueIds.indexOf(valueId)
    noChooseValueIds.splice(index, 1)
  } else {
    // 循环去除当前已选择的 value 属性值 id
    state.currentPropertyArray.forEach((currentPropertyId) => {
      if (currentPropertyId.toString() !== '') {
        return
      }
      // currentPropertyId 为空是反选 填充的
      let index = noChooseValueIds.indexOf(currentPropertyId)
      if (index >= 0) {
        // currentPropertyId 存在于 noChooseValueIds
        noChooseValueIds.splice(index, 1)
      }
    })
  }

  // 当前已选择的 property 数组
  let choosePropertyIds = [] as EmptyArrayType
  if (!isChecked) {
    // 当前已选择的 property
    state.currentPropertyArray.forEach((currentPropertyId, currentValueId) => {
      if (currentPropertyId !== '') {
        // currentPropertyId 为空是反选 填充的
        choosePropertyIds.push(currentValueId)
      }
    })
  } else {
    // 当前点击选择的 property
    choosePropertyIds = [propertyId]
  }

  for (let propertyIndex in propertyList.value) {
    // 当前点击的 property、或者取消选择时候，已选中的 property 不进行处理
    if (choosePropertyIds.indexOf(propertyList.value[propertyIndex]['id']) >= 0) {
      continue
    }
    // 如果当前 property id 不存在于有库存的 SKU 中，则禁用
    for (let valueIndex in propertyList.value[propertyIndex]['values']) {
      propertyList.value[propertyIndex]['values'][valueIndex]['disabled'] =
        noChooseValueIds.indexOf(propertyList.value[propertyIndex]['values'][valueIndex]['id']) < 0 // true 禁用 or false 不禁用
    }
  }
}

// 当前所选属性下，获取所有有库存的 SKU 们
const getCanUseSkuList = () => {
  let newSkus = [] as EmptyArrayType
  for (let sku of skuList.value) {
    // if (sku.stock <= 0) {
    //   continue
    // }
    let isOk = true
    state.currentPropertyArray.forEach((propertyId) => {
      // propertyId 不为空，并且，这个 条 sku 没有被选中，则排除
      if (propertyId.toString() !== '' && sku.value_id_array.indexOf(propertyId) < 0) {
        isOk = false
      }
    })
    if (isOk) {
      newSkus.push(sku)
    }
  }
  return newSkus
}

// 选择规格
const onSelectSku = (propertyId, valueId) => {
  // 清空已选择
  let isChecked = true // 选中 or 取消选中
  if (
    state.currentPropertyArray[propertyId] !== undefined &&
    state.currentPropertyArray[propertyId] === valueId
  ) {
    // 点击已被选中的，删除并填充 ''
    isChecked = false
    state.currentPropertyArray.splice(propertyId, 1, '')
  } else {
    // 选中
    state.currentPropertyArray[propertyId] = valueId
  }
  // 选中的 property 大类
  let choosePropertyId = [] as EmptyArrayType
  state.currentPropertyArray.forEach((currentPropertyId) => {
    console.log(currentPropertyId)

    if (currentPropertyId !== '') {
      // currentPropertyId 为空是反选 填充的
      choosePropertyId.push(currentPropertyId)
    }
  })

  // 当前所选 property 下，所有可以选择的 SKU 们
  let newSkuList = getCanUseSkuList()
  console.log(state.currentPropertyArray)
  console.log(choosePropertyId)

  console.log(propertyList.value)

  // 判断所有 property 大类是否选择完成
  if (choosePropertyId.length === propertyList.value.length && newSkuList.length) {
    newSkuList[0].goods_num = state.selectedSku.goods_num || 1
    state.selectedSku = newSkuList[0]
  } else {
    state.selectedSku = {}
  }

  // 改变 property 禁用状态
  changeDisabled(isChecked, propertyId, valueId)
}

/** 加入购物车 */
const emit = defineEmits(['addCart', 'buy'])
const addCart = async () => {
  // 提交请求
  formLoading.value = true
  try {
    if (state.selectedSku.skuId! <= 0) {
      message.error('请选择规格')
      return
    }
    // 发送操作成功的事件
    emit('addCart', state.selectedSku)

    dialogVisible.value = false
  } finally {
    formLoading.value = false
  }
}
// 立即购买
const onBuy = async () => {
  // 提交请求
  formLoading.value = true
  try {
    if (state.selectedSku.skuId! <= 0) {
      message.error('请选择规格')
      return
    }
    // 发送操作成功的事件
    emit('buy', state.selectedSku)

    dialogVisible.value = false
  } finally {
    formLoading.value = false
  }
}

/** 重置State */

const resetState = () => {
  state.selectedSku = {}
  state.currentPropertyArray = []
  propertyList.value = []
}
</script>
<style lang="scss" scoped>
.goods-title {
  font-weight: 500;
  height: 48px;
  line-height: 24px;
}
.goods-price {
  font-weight: 700;
  color: #ff6200;
}
:deep(.el-input__inner) {
  text-align: center;
}
:deep(.el-image) {
  border-radius: 4px;
  width: 100%;
  height: 0;
  padding-bottom: 100%;
}
:deep(.el-image__inner) {
  position: absolute !important;
}
</style>
